package Map

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Number"
	"reflect"
)

// GetOrDefault 获得元素，如果不存在，以默认值返回
func GetOrDefault(data map[string]interface{}, key string, defaultValue interface{}) interface{} {
	v, ok := data[key]
	if ok {
		return v
	}

	return defaultValue
}

// SetDefaultValue 确认是否存在某个元素，如果不存在，以默认值填入
func SetDefaultValue(data map[string]interface{}, key string, defaultValue interface{}) {
	_, ok := data[key]
	if !ok {
		data[key] = defaultValue
	}
}

// Append 将一个map合并到另一个map中
func Append[T any](data map[string]T, append map[string]T) {
	for k, v := range append {
		data[k] = v
	}
}

func GetKeys[T any](data map[string]T) []string {
	keys := make([]string, len(data))
	for key, _ := range data {
		keys = append(keys, key)
	}

	return keys
}

// Clone 浅拷贝一个副本
func Clone[T any](data map[string]T) map[string]T {
	clone := make(map[string]T)
	for k, v := range data {
		clone[k] = v
	}

	return clone
}

func GetValue(data map[string]interface{}, keys ...interface{}) (interface{}, error) {
	self := data

	for i := 0; i < len(keys)-1; i++ {
		key := keys[i].(string)

		child, ok := self[key]
		if !ok {
			return nil, errors.New("找不到指定的目录")
		}

		val, ok := child.(map[string]interface{})
		if !ok {
			return nil, errors.New("找不到指定的目录")
		}

		self = val
	}

	key := keys[len(keys)-1]
	val := self[key.(string)]

	return val, nil
}

func SetValue(data map[string]interface{}, keys ...interface{}) {
	self := data

	for i := 0; i < len(keys)-2; i++ {
		key := keys[i].(string)

		child, ok := self[key]
		if !ok {
			self[key] = make(map[string]interface{})
		}
		child, ok = self[key]

		self = child.(map[string]interface{})
	}

	key := keys[len(keys)-2]
	val := keys[len(keys)-1]

	self[key.(string)] = val
}

func DelValue(data map[string]interface{}, keys ...interface{}) {
	self := data

	for i := 0; i < len(keys)-1; i++ {
		key := keys[i].(string)

		child, ok := self[key]
		if !ok {
			self[key] = make(map[string]interface{})
		}
		child, ok = self[key]

		self = child.(map[string]interface{})
	}

	key := keys[len(keys)-1]

	delete(self, key.(string))
}

func Clear[T any](list map[string]T) {
	for k, _ := range list {
		delete(list, k)
	}
}

func GetString(data map[string]interface{}, key string, defaultValue string) string {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return data[key].(string)
}

func GetBool(data map[string]interface{}, key string, defaultValue bool) bool {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return data[key].(bool)
}

func GetFloat64(data map[string]interface{}, key string, defaultValue float64) float64 {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return Number.MakeFloat64(data[key])
}

func GetInt64(data map[string]interface{}, key string, defaultValue int64) int64 {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return Number.MakeInt64(data[key])
}

func GetInt(data map[string]interface{}, key string, defaultValue int) int {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return Number.MakeInt(data[key])
}

func GetMap(data map[string]interface{}, key string, defaultValue map[string]interface{}) map[string]interface{} {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return data[key].(map[string]interface{})
}

func GetSlice(data map[string]interface{}, key string, defaultValue []interface{}) []interface{} {
	_, ok := data[key]
	if !ok {
		return defaultValue
	}

	return data[key].([]interface{})
}

func Has(data map[string]interface{}, key string) bool {
	_, ok := data[key]
	return ok
}

func HasNull(data map[string]interface{}, keys ...interface{}) bool {
	for i := 0; i < len(keys); i++ {
		key := keys[i]
		if reflect.TypeOf(key).Kind() != reflect.String {
			continue
		}

		_, ok := data[key.(string)]
		if !ok {
			return true
		}
	}

	return false
}

// ComputeIfAbsent 通过反射板，绕过GO编译器的类型检查，注意：T和E的类型，实际上必须相同
func ComputeIfAbsent[T any, E any](data map[string]E, key string, defaultValue T) T {
	_, ok := data[key]
	if !ok {
		// 通过反射板，绕过GO编译器的类型检查
		v := reflect.ValueOf(defaultValue)
		data[key] = v.Interface().(E)
	}

	// 通过反射板，绕过GO编译器的类型检查
	v := reflect.ValueOf(data)
	mapValue := v.MapIndex(reflect.ValueOf(key))
	if !mapValue.IsValid() {
		return defaultValue
	}

	return mapValue.Interface().(T)
}

func BuildMapByKey(mapList []map[string]interface{}, mapKey string) map[interface{}]interface{} {
	result := make(map[interface{}]interface{})

	for _, data := range mapList {
		key, ok := data[mapKey]
		if ok {
			result[key] = data
		}
	}

	return result
}

func BuildMapByStringKey(mapList []map[string]interface{}, mapKey string) map[string]interface{} {
	result := make(map[string]interface{})

	for _, data := range mapList {
		key, ok := data[mapKey]
		if ok {
			result[key.(string)] = data
		}
	}

	return result
}

func BuildValues[V any](mapData interface{}, valueType V) []V {
	// 使用反射获取map的Type和Value
	mapType := reflect.TypeOf(mapData)
	mapValue := reflect.ValueOf(mapData)

	// 确保反射对象是一个map
	if mapType.Kind() != reflect.Map {
		return nil
	}

	// 遍历map的key
	result := make([]V, 0)
	for _, key := range mapValue.MapKeys() {
		value := mapValue.MapIndex(key)
		result = append(result, value.Interface().(V))
		//	fmt.Printf("Key: %s, Value: %d\n", key.Interface(), value.Interface())
	}

	return result
}

func BuildKeys[K any](mapData interface{}, keyType K) []K {
	// 使用反射获取map的Type和Value
	mapType := reflect.TypeOf(mapData)
	mapValue := reflect.ValueOf(mapData)

	// 确保反射对象是一个map
	if mapType.Kind() != reflect.Map {
		return nil
	}

	// 遍历map的key
	result := make([]K, 0)
	for _, key := range mapValue.MapKeys() {
		result = append(result, key.Interface().(K))
	}

	return result
}
